<?php
namespace App\Services\ThirdPayments\Recharge;

use App\Exceptions\RechargeGatewayException;
use App\Lib\PaymentMap;
use App\Lib\ThirdPartyMap;
use App\Models\RechargeOrder;
use App\Services\ThirdPayments\BankTraits\F1CardBankMap;
use App\Services\ThirdPayments\Contracts\Actions\HrefRedirectAction;
use App\Services\ThirdPayments\Contracts\Actions\QrCodeAction;
use App\Services\ThirdPayments\Contracts\QRCapable;
use App\Services\ThirdPayments\Contracts\RechargeBaseAbstract;
use App\Services\ThirdPayments\Contracts\WAPable;
use Jenssegers\Agent\Agent;
use App\Lib\Code;

class F1CardPayment extends RechargeBaseAbstract implements QRCapable, WAPable
{
    use F1CardBankMap;
    protected $wy_gateway = 'http://www.51card.cn/gateway/wy_pay.asp';
    protected $wx_gateway = 'http://www.51card.cn/gateway/weixinpay/weixinpay.asp';
    protected $qq_gateway = 'http://www.51card.cn/gateway/qqpay/qqpay.asp';
    protected $ali_pc_gateway = 'http://www.51card.cn/gateway/alipay/alipay.asp';
    protected $ali_phone_gateway = 'http://www.51card.cn/gateway/alipay/wap-alipay.asp';
    protected $qq_phone_gateway = 'http://www.51card.cn/gateway/qqpay/wap-qqpay.asp';
    protected $gw_query = 'http://www.51card.cn/gateway/zx_orderquery.asp';

    public function callback(array $data)
    {
        // TODO: Implement callback() method.
        if ($this->veryCallbackSign($data)) {
            if ($data['state'] == 1) {
                return true;
            }
        }
        return false;
    }

    public function veryCallbackSign(array $data)
    {
        // TODO: Implement veryCallbackSign() method.
//        $signStr  = 'customerid=' . $data['customerid'] . '&';
//        $signStr .= 'sd51no=' . $data['sd51no'] . '&';
//        $signStr .= 'sdcustomno=' . $data['sdcustomno'] . '&';
//        $signStr .= 'key=' . $this->getMchKey();
//        $sign = strtoupper(md5($signStr));
//        if ($sign == $data['sign']) {
            $resignStr  = 'sign=' . $data['sign'] . '&';
            $resignStr .= 'customerid=' . $data['customerid'] . '&';
            $resignStr .= 'ordermoney=' . $data['ordermoney'] . '&';
            $resignStr .= 'sd51no=' . $data['sd51no'] . '&';
            $resignStr .= 'state=' . $data['state'] . '&';
            $resignStr .= 'key=' . $this->getMchKey();
            $resign = strtoupper(md5($resignStr));
            if ($resign == $data['resign']) {
                return true;
            }
//        }
        return false;
    }

    public function getOrderNoFromCallback(array $data)
    {
        // TODO: Implement getOrderNoFromCallback() method.
        return $data['sdcustomno'];
    }

    public function getOrderAmtFromCallback(array $data)
    {
        // TODO: Implement getOrderAmtFromCallback() method.
        return $data['ordermoney'];
    }

    public function getThirdNoFromCallback(array $data)
    {
        return $data['sd51no'];
    }

    /**
     * @return mixed
     */
    public function getIdentify(): string
    {
        // TODO: Implement getIdentify() method.
        return ThirdPartyMap::F1Card;
    }

    /**
     *  needs child to achieve
     */
    public function initPaymentMap(): array
    {
        // TODO: Implement initPaymentMap() method.
        return [
            PaymentMap::BANK   => 33,
            PaymentMap::WX     => 32,
            PaymentMap::QQ     => 36,
            PaymentMap::ALI    => 34,
            PaymentMap::ALI_WAP => 52,
            PaymentMap::QQ_WAP => 45
        ];
    }

    public function query(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement query() method.
        $this->setParameter('customerid', $this->getMchId());
        $this->setParameter('sdcustomno', $rechargeOrder->plat_no);
        $this->setParameter('mark', $this->setRemark($rechargeOrder));
        $this->setParameter('sign', $this->querySign());

        $res = curlHttp($this->getGwQuery(), $this->getParameters(), 'get');
        if ($res['http_code'] == 200) {
            $res_arr = $this->convertXmlToArray($res['body']);
            if ($res_arr['state'] == 1) {
                return true;
            }
        }
        return $res['body'];
    }

    public function bankHref(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement bankHref() method.
        $this->setGwPay($this->wy_gateway);
        $mchData = $rechargeOrder->order_data;
        $ext = $this->getExt();
        $this->setParameter('customerid', $this->getMchId());
        $this->setParameter('sdcustomno', $rechargeOrder->plat_no);
        $this->setParameter('ordermoney', $rechargeOrder->order_amt);
        $this->setParameter('cardno', $this->getPaymentMap($mchData['recharge_type']));
        $this->setParameter('faceno', $this->getBank($mchData['bank_code']));
        $this->setParameter('noticeurl', $this->getCallbackUrl());
        $this->setParameter('backurl', $this->getReturnUrl());
        $this->setParameter('endcustomer', array_key_exists('endcustomer', $ext) ? $ext['endcustomer'] : 0);
        $this->setParameter('endip', request()->getClientIp());
        $this->setParameter('remarks', array_key_exists('body', $mchData) ? $mchData['body'] : $this->setRemark($rechargeOrder));
        $this->setParameter('mark', $this->setRemark($rechargeOrder));
        $this->setParameter('sign', $this->payBankSign());
        return $this->getGwPay() . '?' . http_build_query($this->getParameters());
    }

    public function scanCode(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement scanCode() method.
        $mchData = $rechargeOrder->order_data;
        if ($mchData['recharge_type'] == PaymentMap::WX) {
            $this->setGwPay($this->wx_gateway);
        } elseif ($mchData['recharge_type'] == PaymentMap::QQ) {
            $this->setGwPay($this->qq_gateway);
        } elseif ($mchData['recharge_type'] == PaymentMap::ALI) {
            $this->setGwPay($this->ali_pc_gateway);
        }
        $this->setParameter('customerid', $this->getMchId());
        $this->setParameter('sdcustomno', $rechargeOrder->plat_no);
        $this->setParameter('ordermoney', $rechargeOrder->order_amt);
        $this->setParameter('cardno', $this->getPaymentMap($mchData['recharge_type']));
        $this->setParameter('noticeurl', $this->getCallbackUrl());
        $this->setParameter('backurl', $this->getReturnUrl());
        $this->setParameter('mark', array_key_exists('body', $mchData) ? $mchData['body'] : $this->setRemark($rechargeOrder));
        $this->setParameter('ZFtype', 2);
        $this->setParameter('sign', $this->payWxQqSign());
        return $this->getGwPay() . '?' . http_build_query($this->getParameters());
    }

    public function paySign(): string
    {
        // TODO: Implement paySign() method.
    }

    public function querySign(): string
    {
        // TODO: Implement querySign() method.
        $signStr  = 'customerid=' . $this->getParameter('customerid') . '&';
        $signStr .= 'sdcustomno=' . $this->getParameter('sdcustomno') . '&';
        $signStr .= 'mark=' . $this->getParameter('mark') . '&';
        $signStr .= 'key=' . $this->getMchKey();
        return strtoupper(md5($signStr));
    }

    public function showSuccess(): string
    {
        // TODO: Implement showSuccess() method.
        return '<result>1</result>';
    }

    public function initParameters(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement initParameters() method.
    }

    public function payBankSign()
    {
        $signStr  = 'customerid=' . $this->getParameter('customerid') . '&';
        $signStr .= 'sdcustomno=' . $this->getParameter('sdcustomno') . '&';
        $signStr .= 'ordermoney=' . $this->getParameter('ordermoney') . '&';
        $signStr .= 'cardno=' . $this->getParameter('cardno') . '&';
        $signStr .= 'faceno=' . $this->getParameter('faceno') . '&';
        $signStr .= 'key=' . $this->getMchKey();
        return strtoupper(md5($signStr));
    }

    public function payWxQqSign()
    {
        $signStr  = 'customerid=' . $this->getParameter('customerid') . '&';
        $signStr .= 'sdcustomno=' . $this->getParameter('sdcustomno') . '&';
        $signStr .= 'orderAmount=' . $this->getParameter('orderAmount') . '&';
        $signStr .= 'cardno=' . $this->getParameter('cardno') . '&';
        $signStr .= 'noticeurl=' . $this->getParameter('noticeurl') . '&';
        $signStr .= 'backurl=' . $this->getParameter('backurl');
        $signStr .= $this->getMchKey();
        return strtoupper(md5($signStr));
    }

    public function qrCode(RechargeOrder $rechargeOrder)
    {
        // TODO: Implement qrCode() method.
        $mchData = $rechargeOrder->order_data;
        $this->setParameter('customerid', $this->getMchId());
        $this->setParameter('sdcustomno', $rechargeOrder->plat_no);
        $this->setParameter('cardno', $this->getPaymentMap($mchData['recharge_type']));
        $this->setParameter('noticeurl', $this->getCallbackUrl());
        $this->setParameter('backurl', $this->getReturnUrl());
        $this->setParameter('mark', array_key_exists('body', $mchData) ? $mchData['body'] : $this->setRemark($rechargeOrder));
        switch ($mchData['recharge_type']) {
            case PaymentMap::WX:
                $this->setGwPay($this->wx_gateway);
                $this->setParameter('orderAmount', bcmul(100, $rechargeOrder->order_amt));
                $this->setParameter('ZFtype', 2);
                $this->setParameter('sign', $this->payWxQqSign());
                break;
            case PaymentMap::QQ:
                $this->setGwPay($this->qq_gateway);
                $this->setParameter('orderAmount', bcmul(100, $rechargeOrder->order_amt));
                $this->setParameter('sign', $this->payWxQqSign());
                $url = $this->getGwPay() . '?' . http_build_query($this->getParameters());
                return new HrefRedirectAction($url);
                break;
            case PaymentMap::ALI:
                $ext = $this->getExt();
                $this->setGwPay($this->ali_pc_gateway);
                $this->setParameter('ordermoney', $rechargeOrder->order_amt);
                $this->setParameter('endcustomer', array_key_exists('endcustomer', $ext) ? $ext['endcustomer'] : 0);
                $this->setParameter('faceno', 'zfb');
                $this->setParameter('endip', request()->getClientIp());
                $this->setParameter('remarks', $this->setRemark($rechargeOrder));
                $this->setParameter('stype', 1);
                $this->setParameter('ZFtype', 2);
                $this->setParameter('sign', $this->payAliSign());
                break;
            default:
                break;
        }
//        $url = $this->getGwPay() . '?' . http_build_query($this->getParameters());
        try {

            $res = curlHttp($this->getGwPay(), $this->getParameters(), 'get');
            if ($res['http_code'] == 200) {
                $res_arr = $this->convertXmlToArray($res['body']);
                if ($res_arr['state'] == 1) {
                    $code_url = parse_url($res_arr['url'], PHP_URL_QUERY);
                    $qrcode = explode('uuid=', $code_url);
                    if (count($qrcode) == 2) {
                        return new QrCodeAction(urldecode($qrcode[1]));
                    }
                }
                throw new RechargeGatewayException($this, $res['body'], $res_arr['errmsg'], Code::RECHARGE_THIRD_LOG);
            }
        } catch (\Exception $exception) {
            throw new RechargeGatewayException($this, $res['body'], $exception->getMessage(), Code::RECHARGE_THIRD_LOG);
        }
    }

    public function payAliSign()
    {
        $signStr  = 'customerid=' . $this->getParameter('customerid') . '&';
        $signStr .= 'sdcustomno=' . $this->getParameter('sdcustomno') . '&';
        $signStr .= 'ordermoney=' . $this->getParameter('ordermoney') . '&';
        $signStr .= 'cardno=' . $this->getParameter('cardno') . '&';
        $signStr .= 'faceno=' . $this->getParameter('faceno') . '&';
        $signStr .= 'noticeurl=' . $this->getParameter('noticeurl') . '&';
        $signStr .= 'key=' . $this->getMchKey();
        return strtoupper(md5($signStr));
    }

    public function convertXmlToArray($resBody)
    {
        $content = iconv('UTF-8', 'GB2312//IGNORE', $resBody);
        $xml = simplexml_load_string($content);
        $res_arr = [];
        foreach ($xml->items->item as $item) {
            $atts_obj = $item->attributes();
            $attrs = (array) $atts_obj;
            $attrs_array = $attrs['@attributes'];
            $res_arr[$attrs_array['name']] = $attrs_array['value'];
        }
        return $res_arr;
    }

    public function wapReq(RechargeOrder $rechargeOrder)
    {
        $mchData = $rechargeOrder->order_data;
        // TODO: Implement wapReq() method.
        $this->setParameter('customerid', $this->getMchId());
        $this->setParameter('sdcustomno', $rechargeOrder->plat_no);
        $this->setParameter('orderAmount', bcmul(100, $rechargeOrder->order_amt));
        $this->setParameter('cardno', $this->getPaymentMap($mchData['recharge_type']));
        $this->setParameter('noticeurl', $this->getCallbackUrl());
        $this->setParameter('backurl', $this->getReturnUrl());
        $this->setParameter('mark', $this->setRemark($rechargeOrder));
        $this->setParameter('remarks', array_key_exists('body', $mchData) ? $mchData['body'] : 'aiispay:' . $rechargeOrder->plat_no);
        $this->setParameter('sign', $this->payWxQqSign());

        switch ($mchData['recharge_type']) {
            case PaymentMap::QQ_WAP:
                $this->setGwPay($this->qq_phone_gateway);
                break;
            default:
                break;
        }
        return new HrefRedirectAction($this->getGwPay() .'?' . http_build_query($this->getParameters()));



    }
}
